import 'dart:io';

import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:matuo/ble/util/BleUtils.dart';
import 'package:matuo/ble/util/CommandUtils.dart';

import '../utils/Logcat.dart';
import 'util/UUIDUtils.dart';

class BleManager {
  static BleManager? _instance;
  var tag = "BleManager";

  late BluetoothCharacteristic _characteristic, _fileCharacteristic;

  BleManager._();

  static BleManager get instance => _instance ??= BleManager._();

  //2.连接
  Future<void> connect(BluetoothDevice device) async {
    Logcat.instance.w(tag, "开始连接");
    await device.connect();
    Logcat.instance.w(tag, "连接成功");
    if (Platform.isAndroid) {
      Logcat.instance.w(tag, "开始系统配对");
      await device.createBond();
      Logcat.instance.w(tag, "系统配对完成");
    }
    _discoverServices(device);
  }

  //3.发现服务
  Future<void> _discoverServices(BluetoothDevice device) async {
    Logcat.instance.w(tag, "开始发现服务");
    List<BluetoothService> services = await device.discoverServices();
    // List<BluetoothService> services = device.servicesList;
    Logcat.instance.w(tag, "发现服务成功");
    _handlerServices(device, services); //遍历服务列表，找出指定服务
  }

  // 遍历服务列表
  void _handlerServices(
      BluetoothDevice device, List<BluetoothService> services) {
    services.forEach((sItem) {
      String sUuid = sItem.uuid.toString();
      Logcat.instance.w(tag, "主服务${sUuid}");
      if (sUuid == UuidUtils.SET_MODE_SERVICE_UUID.toString()) {
        _readCharacteristics(device, sItem);
      } else if (sUuid == UuidUtils.BIG_FILE_TRANSFER_SERVER_UUID.toString()) {
        _readCharacteristics(device, sItem);
      } else if (sUuid == UuidUtils.DEVICE_INFO_SERVICE.toString()) {
        Logcat.instance.w(tag, "设备信息服务${sUuid}");
        _readCharacteristics(device, sItem);
      } else if (sUuid == UuidUtils.BATTERY_SERVICE_UUID.toString()) {
        Logcat.instance.w(tag, "设备电量服务${sUuid}");
        _readCharacteristics(device, sItem);
      }
    });
  }

  //获取次服务
  Future<void> _readCharacteristics(
      BluetoothDevice device, BluetoothService service) async {
    var characteristics = service.characteristics;
    for (BluetoothCharacteristic cItem in characteristics) {
      String cUuid = cItem.uuid.toString();
      Logcat.instance.w(tag, "次服务${cUuid}");
      if (cUuid == UuidUtils.SET_MODE_CHARACTERISTIC_UUID.toString()) {
        //协议可通知UUID
        _requestMtu(device);
        _setNotificationMode(device, cItem);
        cItem.onValueReceived.listen((data) {
          Logcat.instance
              .w(tag, "协议可通知 ${BleUtils.instance.decimalsToHex(data)}");
        });
      } else if (cUuid == UuidUtils.WRITE_DATA_SERVICE_UUID.toString()) {
        //协议写UUID
        cItem.onValueReceived.listen((data) {
          Logcat.instance
              .w(tag, "协议可写 ${BleUtils.instance.decimalsToHex(data)}");
        });
        _characteristic = cItem;

        var codeUnits = BleUtils.instance.uuidList();
        Logcat.instance.w(
            tag, "随机UUID转List ${BleUtils.instance.decimalsToHex(codeUnits)}");
        var uuidList = codeUnits.skip(codeUnits.length - 8).toList();

        Logcat.instance.w(tag,
            "随机UUID转List取后8位 ${BleUtils.instance.decimalsToHex(uuidList)}");
        var bind = CommandUtils.instance.bindCommand(uuidList);
        Logcat.instance.w(tag, "绑定命令 ${BleUtils.instance.decimalsToHex(bind)}");
        writeCommand(bind);
      } else if (cUuid == UuidUtils.DEVICE_FIRMWARE_INFO.toString()) {
        //协议设备身份标识
        cItem.read();
        cItem.onValueReceived.listen((data) {
          Logcat.instance
              .w(tag, "协议设备身份标识 ${BleUtils.instance.decimalsToHex(data)}");
        });
      } else if (cUuid == UuidUtils.DEVICE_SOFTWARE_INFO.toString()) {
        //协议设备功能标识
        cItem.read();
        cItem.onValueReceived.listen((data) {
          Logcat.instance
              .w(tag, "协议设备功能标识 ${BleUtils.instance.decimalsToHex(data)}");
        });
      } else if (cUuid == UuidUtils.BATTERY_CHARACTERISTIC_UUID.toString()) {
        //协议电量
        cItem.read();
        cItem.onValueReceived.listen((data) {
          Logcat.instance
              .w(tag, "协议电量 ${BleUtils.instance.decimalsToHex(data)}");
        });
      } else if (cUuid ==
          UuidUtils.BIG_FILE_TRANSFER_CHARACTERISTIC_RED_UUID.toString()) {
        _setNotificationMode(device, cItem);
        cItem.onValueReceived.listen((data) {
          Logcat.instance
              .w(tag, "大文件可通知 ${BleUtils.instance.decimalsToHex(data)}");
        });
        _fileCharacteristic = cItem;
      } else if (cUuid ==
          UuidUtils.BIG_FILE_TRANSFER_CHARACTERISTIC_WRITE_UUID.toString()) {
        //大文件协议写UUID
        cItem.onValueReceived.listen((data) {
          Logcat.instance
              .w(tag, "大文件可写 ${BleUtils.instance.decimalsToHex(data)}");
        });
      } else if (cUuid ==
          UuidUtils.BIG_FILE_TRANSFER_CHARACTERISTIC_READ_UUID.toString()) {
        //大文件协议写UUID
        cItem.onValueReceived.listen((data) {
          Logcat.instance
              .w(tag, "大文件可读 ${BleUtils.instance.decimalsToHex(data)}");
        });
      }
    }
  }

  //设置MTU
  Future<void> _requestMtu(BluetoothDevice device) async {
    final mtu = await device.mtu.first;
    Logcat.instance.w(tag, "当前mtu: $mtu 请求设置mtu为512");
    await device.requestMtu(512);
  }

  //设置为Notification模式
  Future<void> _setNotificationMode(
      BluetoothDevice device, BluetoothCharacteristic cItem) async {
    await cItem.setNotifyValue(true); //为指定特征的值设置通知
    // cItem.value.listen((value) {
    //   if (value.isEmpty) return;
    //   Logcat.instance.w(tag, "接收数据  value: ${BleUtils.instance.decimalsToHex(value)}");
    // });
    var descriptors = cItem.descriptors;
    for (BluetoothDescriptor dItem in descriptors) {
      if (dItem.uuid.toString() ==
          UuidUtils.SET_MODE_DESCRIPTOR_UUID.toString()) {
        //找到设置模式的descriptor
        Logcat.instance.w(tag, "设置Notification模式给设备 ");
        dItem.write(UuidUtils.ENABLE_NOTIFICATION_VALUE); //发送Notification模式给设备
        return;
      }
    }
  }

  //发送指令命令
  Future<void> writeCommand(List<int> data) async {
    await _characteristic.write(data);
  }

  //发送文件指令命令
  Future<void> writeFileCommand(List<int> data) async {
    await _fileCharacteristic.write(data);
  }

  //断开连接
  void disconnect(BluetoothDevice device) {
    Logcat.instance.w(tag, "断开连接");
    device.disconnect(); //关闭连接
  }
}
